const {
	Service
} = require('uni-cloud-router')
const {empty , typeOf} = require('../methods/index.js')

module.exports = class courseService extends Service {
	constructor(ctx) {
		super(ctx)
		this.dbCmd = this.db.command
		this.hrCourse = this.db.collection('hr-course')
		this.teachingClass = this.db.collection('teaching-class')
		this.hrUserSchedule = this.db.collection('hr-userSchedule')
	}
	
	/**
	 * 查课程学分
	 * @param {string} course_id 
	 */
	async getCredit(course_id){
		return await this.hrCourse.where({course_id}).get().then((res)=>{
			return res.data[0].credit
		})
	}
	
	/**
	 * 查教学班信息
	 * @param {String} class_id
	 */
	async getClass(class_id){
		var $ = this.db.command.aggregate
		return await this.teachingClass.aggregate()
		 .match({class_id})
		 .lookup({
		    from: 'hr-course',
				let: {
				    classCourse: '$course'
				},
				pipeline: $.pipeline()
					.match(this.dbCmd.expr($.and([
						$.eq(['$course_id', '$$classCourse'])
					])))
				    .project({
						 course_id:1,
				     course_name:1,
						 credit:1
				    })
				    .done(),
				  as: 'courseList',
		  })
			.replaceRoot({
			  newRoot: $.mergeObjects([ $.arrayElemAt(['$courseList', 0]), '$$ROOT' ])
			})
			.lookup({
			   from: 'uni-id-users',
							let: {
							    classUsername: '$username'
							},
							pipeline: $.pipeline()
								.match(this.dbCmd.expr($.and([
									$.eq(['$username', '$$classUsername'])
								])))
							    .project({
							     nickname:1
							    })
							    .done(),
							  as: 'userList',
			 })
			.replaceRoot({
				newRoot: $.mergeObjects([ $.arrayElemAt(['$userList', 0]), '$$ROOT' ])
			})
			.project({
				courseList: 0,
				userList:0
			})
		  .end()
	}
	
	/**
	 * 退课- 用户课程表删除选择的课程 + 教学班可选人数+1
	 * @param {String} username 用户名
	 * @param {String} class_id 教学班ID
	 */
	async dropCourse(username , class_id){
		// 开启事务
		const transaction = await this.db.startTransaction()
		// 获取当前季度课程表
		const userScheduleId = await this.hrUserSchedule.where({username:username})
		.field({'_id':true , 'usedcredit':true , 'schedule':true}).get()
		let {_id , usedcredit , schedule} = userScheduleId.data[0]
		// 获取当前退课学分
		let dropItem = schedule.filter((item)=>{
			console.log(item.class_id,class_id)
			return item.class_id === class_id
		})
		let credit = dropItem[0].credit
		// 返还学分 及 删除课程
		const dropRes = await this.hrUserSchedule.doc(_id).update({
			usedcredit: this.dbCmd.inc(-credit),
			tclass_id : this.dbCmd.pull({
				value : this.dbCmd.in([class_id])
			}),
			schedule : this.dbCmd.pull({
				class_id : this.dbCmd.in([class_id])
			})
		})
		// 返还课程人数
		const increaseRes = await this.teachingClass.where({class_id : class_id})
		.update({optionalNumber:this.dbCmd.inc(1)})
		if(dropRes.updated === 1 && increaseRes.updated === 1) { // 如果都成功才认为退课成功
			await transaction.commit()
			return {code:'', message:"退课成功"}
		 }else{ // 如果一项没成功就认为退课失败
			await transaction.rollback()
			return {code:1001, message:"服务异常,请稍后重试"}
		 }
	}
	
	/**
	 * 选课- 教学班可选人数-1
	 * @param {String} class_id
	 */
	async reduceOptional(class_id){
		const transaction = await this.db.startTransaction()
		const reduceRes = await this.teachingClass.where({
				class_id:class_id,
				optionalNumber:this.dbCmd.gt(0) // 大于1
			})
			.update({
				optionalNumber:this.dbCmd.inc(-1)
			})
			console.log(reduceRes)
		if(reduceRes.updated === 0) { // 如果没成功更新教学班就认为选课失败
				await transaction.rollback()
				return false
		 }else{
			 await transaction.commit()
			 return true
		 }
	}
	
	/**
	 * 选课- 获得课程学分 扣除教学班人数 获得教学班信息
	 * @param {String} course_id 课程id
	 * @param {String} class_id  教学班id
	 */
	async selectionStep(course_id,class_id){
			let courseCredit = await this.service.course.getCredit(course_id)
			let reduceRes = await this.service.course.reduceOptional(class_id)
			if(!reduceRes){
				return({
					code:10001,
					message:class_id+'课程人数已满'
				}) 
			}
			return await this.service.course.getClass(class_id).then((res)=>{
				let data = res.data[0]
				return {data,courseCredit}
			})
	}
	
	/** 选课
	 * @param {Object} username
	 * @param {Object} course_id
	 * @param {Object} class_id
	 */
	async selectionSubmit(username,course_id,class_id){
		const userScheduleId = await this.hrUserSchedule.where({username:username})
		.field({'_id':true , 'usedcredit':true , 'schedule':true , 'credit':true}).get()
		let {_id , usedcredit , schedule , credit} = userScheduleId.data[0]
		let selectItem = schedule.filter((item)=>{return item.class_id === class_id})
		if(!empty(selectItem)){
			return {code:10001 , message:'已选该教学班'}
		}
		let college = await this.hrCourse.where({course_id:course_id}).get().then((res)=>{
			return res.data[0].college
		})
		let {data,courseCredit} = await this.service.course.selectionStep(course_id,class_id)
		if(courseCredit + usedcredit > credit){
			return {code:10002 , message:'超学分了'}
		}
		return await this.hrUserSchedule.doc(_id).update({
			usedcredit: this.dbCmd.inc(courseCredit),
			schedule:this.dbCmd.push(data),
			tclass_id: this.dbCmd.push({"value":[college,course_id,class_id],"key": new Date()})
		}).then((res)=>{
			return {code:'' , message:'选课成功'}
		})
	}
	
	/**
	 * 选课- 选择多门课程
	 * @param {String || Array} course 课程与教学班信息
	 * @param {Number} totalCredits 总学分
	 */
	async selectionCourse(course,totalCredits){
		let result = [] , usedCredits = 0 
		return new Promise((resolve , reject)=>{
			let count = 0
			function isEnd(){
				if(usedCredits > totalCredits){
					reject({
						code: 10001,
						message: '所选课程超过总学分'
					})
				}
				if(++count >= course.length){
					resolve({
						code: '',
						message:'成功',
						data:{usedCredits,result},
					})
				}
			}
			course.map(async (item,index)=>{
				let course_id = item.value[1]
				let class_id  = item.value[2]
				await this.service.course.selectionStep(course_id,class_id).then((res)=>{
					usedCredits += res.courseCredit
					result.push(res.data)
					isEnd()
				})
			})
		})
	}
}